We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

findBy[name] is no longer working. $model->find is returning values it shouldn't.

I have the following code that worked in version 2.0.1, now I get the error "PhalconException: The method 'findByEmail' doesn't exist on model 'User'":

    public function emailExists($request) {
        $email = $request->email;

        $exists = count($this->findByEmail($email)) > 0;
        $user = $this->getDi()->getShared('session')->get('auth');

        if (!empty($user) && $user->email == $email) {
            return true;
        } else if (!$exists) {
            return true;
        }

        return false;
    }

I have since upgraded to 2.0.5. I changed to use the regular find method since I got the error, and it's returning values that it shouldn't. [email protected] is the only user I have right now in my DB. I pass in [email protected] as the $email and it returns the [email protected] record.

    public function emailExists($request) {
        $email = $request->email;

        $exists = count($this->find(["email"=>$email])) > 0;

        $user = $this->getDi()->getShared('session')->get('auth');

        if (!empty($user) && $user->email == $email) {
            return true;
        } else if (!$exists) {
            return true;
        }

        return false;
    }


17.5k
edited Aug '15

I upgraded to 2.0.7 and still get the error "PhalconException: The method 'findByEmail' doesn't exist on model 'User'". Here is my entire User model with the other functions removed:

<?php

use Phalcon\Mvc\Model;
use Phalcon\Mvc\Model\Message;
use Phalcon\Validation;
use Phalcon\Mvc\Model\Validator\Uniqueness;
use Phalcon\Mvc\Model\Validator\Email;
use Phalcon\Mvc\Model\Validator\PresenceOf;
use Phalcon\Mvc\Model\Behavior\SoftDelete;

class User extends Model {
    public $id;
    public $email;
    protected $password;
    public $role;
    public $active;
    protected $active_hash;
    public $first_name;
    public $last_name;
    public $address1;
    public $address2;
    public $city;
    public $state_id;
    public $zip;
    public $country_id;
    public $created;
    public $updated;
    public $deleted;

    public function getPassword() {
        return $this->password;
    }

    public function setPassword($pwd) {
        $this->password = $pwd;
    }

    public function getActiveHash() {
        return $this->active_hash;
    }

    public function setActiveHash($hash) {
        $this->active_hash = $hash;
    }

    public function getCreated() {
        return strtotime($this->created)*1000;
    }

    public function setCreated() {
        $this->created = date('Y-m-d H:i:s');
    }

    public function getUpdated() {
        return strtotime($this->updated)*1000;
    }

    public function getDeleted() {
        return strtotime($this->deleted)*1000;
    }

    public function setDeleted() {
        $this->deleted = date('Y-m-d H:i:s');
    }

    public function initialize() {
        $this->setSource("users");

        $this->skipAttributesOnCreate([
            'active'
        ]);

        $this->addBehavior(new SoftDelete([
            'field' => 'deleted',
            'value' => date('Y-m-d H:i:s')
        ]));

        $this->hasOne('state_id','State','id');
        $this->hasOne('country_id','Country','id');
        $this->hasOne('id','Vendor','user_id');
    }

    public function validation() {
        $this->validate(new PresenceOf(
            array(
                "field"   => "email",
                "message" => "Email address is required."
            )
        ));

        $this->validate(new PresenceOf(
            array(
                "field"   => "password",
                "message" => "Password is required."
            )
        ));

        $this->validate(new Email(
            array(
                "field"   => "email",
                "message" => "Email address is invalid."
            )
        ));

        $this->validate(new Uniqueness(
            array(
                "field"   => "email",
                "message" => "Email address is taken."
            )
        ));

        if ($this->validationHasFailed() == true) {
            return false;
        }
    }

    public function beforeValidationOnCreate() {
        $this->created = date('Y-m-d H:i:s');
        $this->updated = date('Y-m-d H:i:s');
    }

    public function afterCreate() {
        $this->sendActivationEmail();
    }

    public function beforeValidationOnUpdate() {
        $this->updated = date('Y-m-d H:i:s');
    }

    public function emailExists($request) {
        $email = $request->email;

        $exists = count($this->findByEmail($email)) > 0;
        $user = $this->getDi()->getShared('session')->get('auth');

        if (!empty($user) && $user->email == $email) {
            return true;
        } else if (!$exists) {
            return true;
        }

        return false;
    }
}


17.5k

Got regular find working, but findByEmail is still throwing an error...

    public function emailExists($request) {
        $email = $request->email;

        $exists = count($this->find("email='$email'")) > 0;

        $user = $this->getDi()->getShared('session')->get('auth');

        if (!empty($user) && $user->email == $email) {
            return true;
        } else if (!$exists) {
            return true;
        }

        return false;
    }


17.5k
edited Aug '15

I do have an actual field called email and I'm not caching models meta-data.

I will pass the entire call stack when I get home. It's called from a controller. I will also test another section where I use finders to see if that still works.



17.5k

Here is my ajax request:

    //call center is an angular service I have set up that does a basic $http.post() and $http.get()
    $scope.validEmail = function() {
        var u = $scope.user;
        if (u.email && u.email != "") {
            CallCenter.post("/ajax/valid-email",u).then(
                function(data){
                    if (data.user) {
                        Util.showError("Email Address is taken.");
                    }
                }
            );
        }
    }

Here is my route:

    $router->addPost("/ajax/valid-email",[
        'controller' => 'noauthajax',
        'action' => 'validemail'
    ]);

Here is my controller function:

    public function validemailAction() {
        $response = $this->getResponse();
        $request = $this->getRequest();

        $user = new User();

        if ($user->emailExists($request)) {
            $response['success'] = true;
        } else {
            $response['error'] = "Email address is taken.";
        }

        echo json_encode($response);
        die();
    }

Here is my model function:

    public function emailExists($request) {
        $email = $request->email;

        $exists = count($this->findByEmail($email)) > 0;
        $user = $this->getDi()->getShared('session')->get('auth');

        if (!empty($user) && $user->email == $email) {
            return true;
        } else if (!$exists) {
            return true;
        }

        return false;
    }

I checked another place in my app that uses the findBy function and it worked. The major difference between the two is that the other area is not being called via ajax.

It's very unlikely that Phalcon raises a bug in the ORM if the request is made via ajax.



17.5k
edited Aug '15

Yeah, seems strange to me too. No idea why it's not working unless it's breaking inside of the count()... That's another difference. Anyway, I switched to normal find() and it's working... Just weird that it stopped working in the first place.



12.9k

Maybe you overrode static method ::find()? If so, you have to return at least parent::find($parameters) in order to let magic static methods findBy[something] work properly.

Other possible issue: in your Model you have a property called $email: if in your DB the name is that same it's ok, otherwise you should use ::columnMap() to tell the Model how to properly translate it. Have a look at this (after the two black examples):

https://docs.phalcon.io/en/latest/reference/models.html#public-properties-vs-setters-getters